﻿// SyntheticDataGenerator.Core.PatternSetIterator
//
// (c) 2011 Arthur Pitman
//
// Part of Market-Basket Synthetic Data Generator
// A C# adaptation of the IBM Quest Market-Basket Synthetic Data Generator
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// (Version 2) as published by the Free Software Foundation.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public
// License (Version 2) along with this program; if not, write to 
// the Free Software Foundation, Inc., 
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
// or see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SyntheticDataGenerator.Generators;

namespace SyntheticDataGenerator.Core
{
	/// <summary>
	/// Iterates through <see cref="Patterns"/>
	/// </summary>
	public class PatternSetIterator
	{
		/// <summary>
		/// Source of randomess
		/// </summary>
		protected UniformGenerator uniformGenerator = new UniformGenerator();

		/// <summary>
		/// The underlying <see cref="PatternSet"/> used
		/// </summary>
		protected PatternSet patternSet;

		/// <summary>
		/// Index of most recently retrieved <see cref="Pattern"/>, used as a flag for ungetting patterns
		/// </summary>
		protected int lastPattern;

		/// <summary>
		/// Initializes a new <see cref="PatternSetIterator"/> instance on the specified <see cref="PatternSet"/>
		/// </summary>
		/// <param name="patternSet"></param>
		public PatternSetIterator(PatternSet patternSet)
		{
			this.patternSet = patternSet;
			lastPattern = 0;
		}
		
		/// <summary>
		/// Returns a random <see cref="Pattern"/>
		/// </summary>
		/// <returns></returns>
		public Pattern GetPattern()
		{
			// return any pattern previously put back
			if (lastPattern < 0)
			{
				lastPattern = -lastPattern;
				return patternSet.GetPattern(lastPattern);            
			}

			// find the pattern using the table cumulative probabilities
			double r = uniformGenerator.Next();
			int i = (int)(r * patternSet.PatternCount);
			if (i == patternSet.PatternCount)
				i--;
			while ((i < (patternSet.PatternCount - 1)) && (r > patternSet.CumulativeProbabilities[i]))
				i++;
			while ((i > 0) && (r < patternSet.CumulativeProbabilities[i - 1]))
				i--;

			// note index of the pattern and return it
			lastPattern = i;
			return patternSet.GetPattern(i);   
		}

		/// <summary>
		/// Puts the last <see cref="Pattern"/> back
		/// </summary>
		public void UnGetPattern()
		{
			lastPattern = -lastPattern;
		}

	}
}
